package cn.jannal.lock.web;

import cn.jannal.lock.exception.BusinessException;
import cn.jannal.lock.service.ProductStockService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class ProductStockController {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Resource
    private ProductStockService productStockService;

    /**
     * 乐观锁秒杀一
     * 通过外围的调用来控制重试次数，就是在多个事务中执行
     * 乐观锁是需要加上id+version的联合索引的，否则做不到在不加锁(不阻塞)的情况下实现更新
     * @param productId
     * @param productNum
     * @return
     */
    @RequestMapping("/optimisticLock/spikeProductStock1")
    public String spikeProductStock1(Long productId, Long productNum) {

        for (int i = 0; i <= 3; i++) {
            try {
                productStockService.updateProductNum(productId, productNum);
                break;
            } catch (BusinessException e) {
                logger.error(e.getMessage());
                if (i == 3) {
                    logger.error("最后一次重试失败：{}", e.getMessage());
                    return e.getMessage();
                }
            }
        }
        return "秒杀成功";
    }

    /**
     * 通过内部来控制重试次数，在一个事务中
     * @param productId
     * @param productNum
     * @return
     */
    @RequestMapping("/optimisticLock/spikeProductStock0")
    public String spikeProductStock0(Long productId, Long productNum) {

        try {
            productStockService.updateProductNum1(productId, productNum);
        } catch (BusinessException e) {
            logger.error(e.getMessage());
            return e.getMessage();
        }
        return "秒杀成功";

    }

    /**
     * 乐观锁秒杀二
     * 
     * @param productId
     * @param productNum
     * @return
     */
    @RequestMapping("/optimisticLock/spikeProductStock2")
    public String spikeProductStock2(Long productId, Long productNum) {
        try {
            productStockService.updateProductNum2(productId, productNum);
        } catch (BusinessException e) {
            return e.getMessage();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return "操作异常";
        }
        return "秒杀成功";
    }


    /**
     * 使用mysql自己的锁，不进行查询，只进行一条更新
     * @param productId
     * @param productNum
     * @return
     */
    @RequestMapping("/optimisticLock/spikeProductStock3")
    public String spikeProductStock22(Long productId, Long productNum) {
        try {
            productStockService.updateProductNum22(productId, productNum);
        } catch (BusinessException e) {
            return e.getMessage();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return "操作异常";
        }
        return "秒杀成功";
    }


    /**
     * 悲观锁秒杀
     * 
     * @param productId
     * @param productNum
     * @return
     */
    @RequestMapping("/pessimisticlock/spikeProductStock0")
    public String spikeProductStock3(Long productId, Long productNum) {
        try {
            productStockService.updateProductNum3(productId, productNum);
        } catch (BusinessException e) {
            return e.getMessage();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return "操作异常";
        }
        return "秒杀成功";
    }
    
    /**
     * 分布式锁防止数据重复插入
     */
    @RequestMapping("/distributedlock/saveOrUpdateRedis")
    public String saveOrUpdateRedis(Long productId, Long productNum){
        try {
            productStockService.saveOrUpdate(productId, productNum);
        } catch (BusinessException e) {
            return e.getMessage();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return "操作异常";
        }
        return "操作成功";
    }
    /**
     * 分布式锁防止数据重复插入
     */
    @RequestMapping("/distributedlock/saveOrUpdateMysql")
    public String saveOrUpdateMysql(Long productId, Long productNum){
        try {
            productStockService.saveOrUpdateMysql(productId, productNum);
        } catch (BusinessException e) {
            return e.getMessage();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return "操作异常";
        }
        return "操作成功";
    }
    /**
     * 分布式锁防止数据重复插入
     */
    @RequestMapping("/distributedlock/saveOrUpdateZookeeper")
    public String saveOrUpdateZookeeper(Long productId, Long productNum){
        try {
            productStockService.saveOrUpdateZookeeper(productId, productNum);
        } catch (BusinessException e) {
            return e.getMessage();
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return "操作异常";
        }
        return "操作成功";
    }
  
}
